/**
 *
 * Color picker
 * Author: Stefan Petre www.eyecon.ro
 * 
 * Dual licensed under the MIT and GPL licenses
 * 
 */
(function ($) {
	var ColorPicker = function () {
		var
			ids = {},
			inAction,
			charMin = 65,
			visible,
			tpl = '<div class="colorpicker"><div class="colorpicker_color"><div><div></div></div></div><div class="colorpicker_hue"><div></div></div><div class="colorpicker_new_color"></div><div class="colorpicker_current_color"></div><div class="colorpicker_hex"><input type="text" maxlength="6" size="6" /></div><div class="colorpicker_rgb_r colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_g colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_h colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_s colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_submit"></div></div>',
			defaults = {
				eventName: 'click',
				onShow: function () {},
				onBeforeShow: function(){},
				onHide: function () {},
				onChange: function () {},
				onSubmit: function () {},
				color: 'ff0000',
				livePreview: true,
				flat: false
			},
			fillRGBFields = function  (hsb, cal) {
				var rgb = HSBToRGB(hsb);
				$(cal).data('colorpicker').fields
					.eq(1).val(rgb.r).end()
					.eq(2).val(rgb.g).end()
					.eq(3).val(rgb.b).end();
			},
			fillHSBFields = function  (hsb, cal) {
				$(cal).data('colorpicker').fields
					.eq(4).val(hsb.h).end()
					.eq(5).val(hsb.s).end()
					.eq(6).val(hsb.b).end();
			},
			fillHexFields = function (hsb, cal) {
				$(cal).data('colorpicker').fields
					.eq(0).val(HSBToHex(hsb)).end();
			},
			setSelector = function (hsb, cal) {
				$(cal).data('colorpicker').selector.css('backgroundColor', '#' + HSBToHex({h: hsb.h, s: 100, b: 100}));
				$(cal).data('colorpicker').selectorIndic.css({
					left: parseInt(150 * hsb.s/100, 10),
					top: parseInt(150 * (100-hsb.b)/100, 10)
				});
			},
			setHue = function (hsb, cal) {
				$(cal).data('colorpicker').hue.css('top', parseInt(150 - 150 * hsb.h/360, 10));
			},
			setCurrentColor = function (hsb, cal) {
				$(cal).data('colorpicker').currentColor.css('backgroundColor', '#' + HSBToHex(hsb));
			},
			setNewColor = function (hsb, cal) {
				$(cal).data('colorpicker').newColor.css('backgroundColor', '#' + HSBToHex(hsb));
			},
			keyDown = function (ev) {
				var pressedKey = ev.charCode || ev.keyCode || -1;
				if ((pressedKey > charMin && pressedKey <= 90) || pressedKey == 32) {
					return false;
				}
				var cal = $(this).parent().parent();
				if (cal.data('colorpicker').livePreview === true) {
					change.apply(this);
				}
			},
			change = function (ev) {
				var cal = $(this).parent().parent(), col;
				if (this.parentNode.className.indexOf('_hex') > 0) {
					cal.data('colorpicker').color = col = HexToHSB(fixHex(this.value));
				} else if (this.parentNode.className.indexOf('_hsb') > 0) {
					cal.data('colorpicker').color = col = fixHSB({
						h: parseInt(cal.data('colorpicker').fields.eq(4).val(), 10),
						s: parseInt(cal.data('colorpicker').fields.eq(5).val(), 10),
						b: parseInt(cal.data('colorpicker').fields.eq(6).val(), 10)
					});
				} else {
					cal.data('colorpicker').color = col = RGBToHSB(fixRGB({
						r: parseInt(cal.data('colorpicker').fields.eq(1).val(), 10),
						g: parseInt(cal.data('colorpicker').fields.eq(2).val(), 10),
						b: parseInt(cal.data('colorpicker').fields.eq(3).val(), 10)
					}));
				}
				if (ev) {
					fillRGBFields(col, cal.get(0));
					fillHexFields(col, cal.get(0));
					fillHSBFields(col, cal.get(0));
				}
				setSelector(col, cal.get(0));
				setHue(col, cal.get(0));
				setNewColor(col, cal.get(0));
				cal.data('colorpicker').onChange.apply(cal, [col, HSBToHex(col), HSBToRGB(col)]);
			},
			blur = function (ev) {
				var cal = $(this).parent().parent();
				cal.data('colorpicker').fields.parent().removeClass('colorpicker_focus');
			},
			focus = function () {
				charMin = this.parentNode.className.indexOf('_hex') > 0 ? 70 : 65;
				$(this).parent().parent().data('colorpicker').fields.parent().removeClass('colorpicker_focus');
				$(this).parent().addClass('colorpicker_focus');
			},
			downIncrement = function (ev) {
				var field = $(this).parent().find('input').focus();
				var current = {
					el: $(this).parent().addClass('colorpicker_slider'),
					max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255),
					y: ev.pageY,
					field: field,
					val: parseInt(field.val(), 10),
					preview: $(this).parent().parent().data('colorpicker').livePreview					
				};
				$(document).bind('mouseup', current, upIncrement);
				$(document).bind('mousemove', current, moveIncrement);
			},
			moveIncrement = function (ev) {
				ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val + ev.pageY - ev.data.y, 10))));
				if (ev.data.preview) {
					change.apply(ev.data.field.get(0), [true]);
				}
				return false;
			},
			upIncrement = function (ev) {
				change.apply(ev.data.field.get(0), [true]);
				ev.data.el.removeClass('colorpicker_slider').find('input').focus();
				$(document).unbind('mouseup', upIncrement);
				$(document).unbind('mousemove', moveIncrement);
				return false;
			},
			downHue = function (ev) {
				var current = {
					cal: $(this).parent(),
					y: $(this).offset().top
				};
				current.preview = current.cal.data('colorpicker').livePreview;
				$(document).bind('mouseup', current, upHue);
				$(document).bind('mousemove', current, moveHue);
			},
			moveHue = function (ev) {
				change.apply(
					ev.data.cal.data('colorpicker')
						.fields
						.eq(4)
						.val(parseInt(360*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.y))))/150, 10))
						.get(0),
					[ev.data.preview]
				);
				return false;
			},
			upHue = function (ev) {
				fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
				fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
				$(document).unbind('mouseup', upHue);
				$(document).unbind('mousemove', moveHue);
				return false;
			},
			downSelector = function (ev) {
				var current = {
					cal: $(this).parent(),
					pos: $(this).offset()
				};
				current.preview = current.cal.data('colorpicker').livePreview;
				$(document).bind('mouseup', current, upSelector);
				$(document).bind('mousemove', current, moveSelector);
			},
			moveSelector = function (ev) {
				change.apply(
					ev.data.cal.data('colorpicker')
						.fields
						.eq(6)
						.val(parseInt(100*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.pos.top))))/150, 10))
						.end()
						.eq(5)
						.val(parseInt(100*(Math.max(0,Math.min(150,(ev.pageX - ev.data.pos.left))))/150, 10))
						.get(0),
					[ev.data.preview]
				);
				return false;
			},
			clickSelector = function(ev){
				var current = {
					cal: $(this).parent(),
					pos: $(this).offset()
				};
				ev.data = {
					cal: $(this).parent(),
					pos: $(this).offset(),
					preview:true
				};	
				moveSelector(ev);
				fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
				fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));				
			},			
			upSelector = function (ev) {
				fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
				fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
				$(document).unbind('mouseup', upSelector);
				$(document).unbind('mousemove', moveSelector);
				return false;
			},
			enterSubmit = function (ev) {
				$(this).addClass('colorpicker_focus');
			},
			leaveSubmit = function (ev) {
				$(this).removeClass('colorpicker_focus');
			},
			clickSubmit = function (ev) {
				var cal = $(this).parent();
				var col = cal.data('colorpicker').color;
				cal.data('colorpicker').origColor = col;
				setCurrentColor(col, cal.get(0));
				cal.data('colorpicker').onSubmit(col, HSBToHex(col), HSBToRGB(col), cal.data('colorpicker').el);
			},
			show = function (ev) {
				var cal = $('#' + $(this).data('colorpickerId'));
				var callback = cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]);
				if(callback === false){
					return false;
				}
				var pos = $(this).offset();
				var viewPort = getViewport();
				var top = pos.top + this.offsetHeight;
				var left = pos.left;
				if (top + 176 > viewPort.t + viewPort.h) {
					top -= this.offsetHeight + 176;
				}
				if (left + 356 > viewPort.l + viewPort.w) {
					left -= 356;
				}
				cal.css({left: left + 'px', top: top + 'px'});
				if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) != false) {
					cal.show();
				}
				$(document).bind('mousedown', {cal: cal}, hide);
				return false;
			},
			hide = function (ev) {
				if (!isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
					if (ev.data.cal.data('colorpicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) {
						ev.data.cal.hide();
					}
					$(document).unbind('mousedown', hide);
				}
			},
			isChildOf = function(parentEl, el, container) {
				if (parentEl == el) {
					return true;
				}
				if (parentEl.contains) {
					return parentEl.contains(el);
				}
				if ( parentEl.compareDocumentPosition ) {
					return !!(parentEl.compareDocumentPosition(el) & 16);
				}
				var prEl = el.parentNode;
				while(prEl && prEl != container) {
					if (prEl == parentEl)
						return true;
					prEl = prEl.parentNode;
				}
				return false;
			},
			getViewport = function () {
				var m = document.compatMode == 'CSS1Compat';
				return {
					l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
					t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
					w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
					h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
				};
			},
			fixHSB = function (hsb) {
				return {
					h: Math.min(360, Math.max(0, hsb.h)),
					s: Math.min(100, Math.max(0, hsb.s)),
					b: Math.min(100, Math.max(0, hsb.b))
				};
			}, 
			fixRGB = function (rgb) {
				return {
					r: Math.min(255, Math.max(0, rgb.r)),
					g: Math.min(255, Math.max(0, rgb.g)),
					b: Math.min(255, Math.max(0, rgb.b))
				};
			},
			fixHex = function (hex) {
				var len = 6 - hex.length;
				if (len > 0) {
					var o = [];
					for (var i=0; i<len; i++) {
						o.push('0');
					}
					o.push(hex);
					hex = o.join('');
				}
				return hex;
			}, 
			HexToRGB = function (hex) {
				var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
				return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)};
			},
			HexToHSB = function (hex) {
				return RGBToHSB(HexToRGB(hex));
			},
			RGBToHSB = function (rgb) {
				var hsb = {
					h: 0,
					s: 0,
					b: 0
				};
				var min = Math.min(rgb.r, rgb.g, rgb.b);
				var max = Math.max(rgb.r, rgb.g, rgb.b);
				var delta = max - min;
				hsb.b = max;
				if (max != 0) {
					
				}
				hsb.s = max != 0 ? 255 * delta / max : 0;
				if (hsb.s != 0) {
					if (rgb.r == max) {
						hsb.h = (rgb.g - rgb.b) / delta;
					} else if (rgb.g == max) {
						hsb.h = 2 + (rgb.b - rgb.r) / delta;
					} else {
						hsb.h = 4 + (rgb.r - rgb.g) / delta;
					}
				} else {
					hsb.h = -1;
				}
				hsb.h *= 60;
				if (hsb.h < 0) {
					hsb.h += 360;
				}
				hsb.s *= 100/255;
				hsb.b *= 100/255;
				return hsb;
			},
			HSBToRGB = function (hsb) {
				var rgb = {};
				var h = Math.round(hsb.h);
				var s = Math.round(hsb.s*255/100);
				var v = Math.round(hsb.b*255/100);
				if(s == 0) {
					rgb.r = rgb.g = rgb.b = v;
				} else {
					var t1 = v;
					var t2 = (255-s)*v/255;
					var t3 = (t1-t2)*(h%60)/60;
					if(h==360) h = 0;
					if(h<60) {rgb.r=t1;	rgb.b=t2; rgb.g=t2+t3}
					else if(h<120) {rgb.g=t1; rgb.b=t2;	rgb.r=t1-t3}
					else if(h<180) {rgb.g=t1; rgb.r=t2;	rgb.b=t2+t3}
					else if(h<240) {rgb.b=t1; rgb.r=t2;	rgb.g=t1-t3}
					else if(h<300) {rgb.b=t1; rgb.g=t2;	rgb.r=t2+t3}
					else if(h<360) {rgb.r=t1; rgb.g=t2;	rgb.b=t1-t3}
					else {rgb.r=0; rgb.g=0;	rgb.b=0}
				}
				return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)};
			},
			RGBToHex = function (rgb) {
				var hex = [
					rgb.r.toString(16),
					rgb.g.toString(16),
					rgb.b.toString(16)
				];
				$.each(hex, function (nr, val) {
					if (val.length == 1) {
						hex[nr] = '0' + val;
					}
				});
				return hex.join('');
			},
			HSBToHex = function (hsb) {
				return RGBToHex(HSBToRGB(hsb));
			},
			restoreOriginal = function () {
				var cal = $(this).parent();
				var col = cal.data('colorpicker').origColor;
				cal.data('colorpicker').color = col;
				fillRGBFields(col, cal.get(0));
				fillHexFields(col, cal.get(0));
				fillHSBFields(col, cal.get(0));
				setSelector(col, cal.get(0));
				setHue(col, cal.get(0));
				setNewColor(col, cal.get(0));
			};
		return {
			init: function (opt) {
				opt = $.extend({}, defaults, opt||{});
				if (typeof opt.color == 'string') {
					opt.color = HexToHSB(opt.color);
				} else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) {
					opt.color = RGBToHSB(opt.color);
				} else if (opt.color.h != undefined && opt.color.s != undefined && opt.color.b != undefined) {
					opt.color = fixHSB(opt.color);
				} else {
					return this;
				}
				return this.each(function () {
					if (!$(this).data('colorpickerId')) {
						var options = $.extend({}, opt);
						options.origColor = opt.color;
						var id = 'collorpicker_' + parseInt(Math.random() * 1000);
						$(this).data('colorpickerId', id);
						var cal = $(tpl).attr('id', id);
						if (options.flat) {
							cal.appendTo(this).show();
						} else {
							cal.appendTo(document.body);
						}
						options.fields = cal
											.find('input')
												.bind('keyup', keyDown)
												.bind('change', change)
												.bind('blur', blur)
												.bind('focus', focus);
						cal
							.find('span').bind('mousedown', downIncrement).end()
							.find('>div.colorpicker_current_color').bind('click', restoreOriginal);
						options.selector = cal.find('div.colorpicker_color').bind('mousedown', downSelector).bind('click',clickSelector);
						options.selectorIndic = options.selector.find('div div');
						options.el = this;
						options.hue = cal.find('div.colorpicker_hue div');
						cal.find('div.colorpicker_hue').bind('mousedown', downHue);
						options.newColor = cal.find('div.colorpicker_new_color');
						options.currentColor = cal.find('div.colorpicker_current_color');
						cal.data('colorpicker', options);
						cal.find('div.colorpicker_submit')
							.bind('mouseenter', enterSubmit)
							.bind('mouseleave', leaveSubmit)
							.bind('click', clickSubmit);
						fillRGBFields(options.color, cal.get(0));
						fillHSBFields(options.color, cal.get(0));
						fillHexFields(options.color, cal.get(0));
						setHue(options.color, cal.get(0));
						setSelector(options.color, cal.get(0));
						setCurrentColor(options.color, cal.get(0));
						setNewColor(options.color, cal.get(0));
						if (options.flat) {
							cal.css({
								position: 'relative',
								display: 'block'
							});
						} else {
							$(this).bind(options.eventName, show);
						}
					}
				});
			},
			showPicker: function() {
				return this.each( function () {
					if ($(this).data('colorpickerId')) {
						show.apply(this);
					}
				});
			},
			hidePicker: function() {
				return this.each( function () {
					if ($(this).data('colorpickerId')) {
						$('#' + $(this).data('colorpickerId')).hide();
					}
				});
			},
			setColor: function(col) {
				if (typeof col == 'string') {
					col = HexToHSB(col);
				} else if (col.r != undefined && col.g != undefined && col.b != undefined) {
					col = RGBToHSB(col);
				} else if (col.h != undefined && col.s != undefined && col.b != undefined) {
					col = fixHSB(col);
				} else {
					return this;
				}
				return this.each(function(){
					if ($(this).data('colorpickerId')) {
						var cal = $('#' + $(this).data('colorpickerId'));
						cal.data('colorpicker').color = col;
						cal.data('colorpicker').origColor = col;
						fillRGBFields(col, cal.get(0));
						fillHSBFields(col, cal.get(0));
						fillHexFields(col, cal.get(0));
						setHue(col, cal.get(0));
						setSelector(col, cal.get(0));
						setCurrentColor(col, cal.get(0));
						setNewColor(col, cal.get(0));
					}
				});
			}
		};
	}();
	$.fn.extend({
		ColorPicker: ColorPicker.init,
		ColorPickerHide: ColorPicker.hidePicker,
		ColorPickerShow: ColorPicker.showPicker,
		ColorPickerSetColor: ColorPicker.setColor
	});
})(jQuery);


angular.module('zixys.directives',[])

    .directive('zixysMainWrapper', function() {

        return {
            restrict: 'C',
            replace: false,
            scope: {},
            //require: 'zixysMainCtrl',
            //controller: 'zixysMainCtrl',
            template:'<div id="zixys-wrap">'+
                        '<div id="zixys-tab-wrap"></div>'+
                        '<div id="zixys-content-wrap"></div>'+
                     '</div>',

            link: function(scope, element, attrs) {
                scope.$root.$contentWrapper = element.find('#zixys-content-wrap');
                scope.$root.$tabsWrapper = element.find('#zixys-tab-wrap');
                
                scope.$root.addTab = function(tabTitle,contentName,$compile){
                    
                    var tab = $('<span class="zixys-tab" src="zixys-'+contentName+'">'+tabTitle+'</div>');
                    var content = $('<div id="zixys-'+contentName+'" class="'+contentName+'" ></div>');
                    scope.$root.$contentWrapper.append(content);
                    scope.$root.$tabsWrapper.append(tab);
                    
                    $compile(content)(scope.$root);
                    $compile(tab)(scope.$root);
                };
                
                scope.$root.addButton = function(buttonTitle,className,$compile){
                    var button = $('<b class="'+className+' zixys-button" title="'+buttonTitle+'"></b>');
                    scope.$root.$tabsWrapper.prepend(button);
                    $compile(button)(scope.$root);
                }
                
                scope.$root.$broadcast('zixysDomReady', {
                    contentWrapper:scope.$root.$contentWrapper,
                    tabsWrapper:scope.$root.$tabsWrapper
                })    
            }
        }
        
    })
    
    .directive('zixysTab',function(){
        return {
            restrict: 'C',
            replace: false,
            scope: {},

            link: function($scope, element, attrs) {
                var contentWrapper = $scope.$root.$contentWrapper;
                var tabContent = contentWrapper.find('#'+attrs.src);
                var tabWrapper = $scope.$root.$tabsWrapper;
                
                element.click(function(){
                    tabWrapper.children().removeClass('zActive');
                    element.addClass('zActive');
                    contentWrapper.children().hide();
                    tabContent.show();
                    $scope.$root.$activeTab = tabContent;
                }); 
                
                //make first tab active
                tabWrapper.children('span.zixys-tab:eq(0)').addClass('zActive');
                $scope.$root.$activeTab = contentWrapper.children().hide().filter(':eq(0)');
                $scope.$root.$activeTab.show();
                $scope.$root.$broadcast('tabsReady',$scope.$root.$activeTab);
            }
        }
    })
    
    .directive('zixysInnerTab',function(){
        return {
            restrict: 'C',
            replace: false,
            scope: {},
            link:function($scope, element, attrs){
                
                $scope.$root.$on('tabsReady',function(event,activeTab){
                    var tabs = element.children();
                    var contents = activeTab.find('#'+attrs.src).children();
                        
                    tabs.click(function(){
                        var self = this;
                        var index = 0;
                        tabs.each(function(i,elem){
                           if(elem === self){
                               index = i;
                               return false;
                           } 
                        });
                        contents.hide();
                        contents.filter(':eq('+index+')').show();
                        tabs.removeClass('zActive').filter(':eq('+index+')').addClass('zActive');
                    });
                    
                    contents.hide().filter(':eq(0)').show();
                    tabs.filter(':eq(0)').addClass('zActive');
                });
                

            }
        }
    })
    
    .directive('zixysButton',function(){
        return {
            restrict: 'A',
            replace: true,
            template:'<em class="zixys-button"><i></i></em>',
            scope: {
                button:'=zixysButton'
            },

            link: function($scope, element, attrs) {
                var defaults ={
                    iconClass:'',
                    onPress: angular.noop,
                    onRelease: angular.noop,
                    disable:false
                }, disabled;
                $scope.button = $.extend({}, defaults, $scope.button);
                element.children().addClass($scope.button.iconClass);
                
                element.click(function(event){
                    if(disabled) return;
                    if(element.hasClass('zixys-sbutton-pressed')){
                        element.removeClass('zixys-sbutton-pressed');
                        $scope.button.onPress();
                    }else{
                        element.addClass('zixys-sbutton-pressed');
                        $scope.button.onRelease();
                    }
                    event.stopImmediatePropagation();
                });

                $scope.button.press = function(){
                    if(disabled) return;
                    if(!element.hasClass('zixys-sbutton-pressed')){
                        element.addClass('zixys-sbutton-pressed');
                        $scope.button.onPress();
                    }
                }

                $scope.button.release = function(){
                    if(disabled) return;
                    if(element.hasClass('zixys-sbutton-pressed')){
                        element.removeClass('zixys-sbutton-pressed');
                        $scope.button.onRelease();
                    }                    
                }

                $scope.button.enable = function(){
                   element.removeClass('zixys-sbutton-disabled');
                    disabled = false;
                }
                
                $scope.button.disable = function(){
                    $scope.button.release();
                    element.addClass('zixys-sbutton-disabled');
                    disabled = true;
                }
                
                $scope.button.isEnable = function(){
                    return !disabled;
                }
                
                $scope.button.isPressed = function(){
                    return element.hasClass('zixys-sbutton-pressed');
                }                
                
                if($scope.button.initStateDisabled){
                    $scope.button.disable();
                }
            }
        }
    })
    
    .directive('zixysSpinner',function(){
        return {
            restrict: 'C',
            replace: false,
            scope: {
                output:'=ngModel'
            },
            link:function($scope, element, attr){
                
                var spinner = new zixysSpinner(element,$scope);
                
                element.keydown(function(event){

                    switch(event.keyCode)
                    {
                    case 38:
                        spinner.increment = 1;
                        break;
                    case 40:
                        spinner.increment = -1;
                        break;
                    default:
                        return;
                    }

                    if(spinner.isSpinning){
                        return;
                    }else{
                        spinner.isSpinning = true;
                    }
                    
                    spinner.start();

                }).keyup(function(event){
                    spinner.stop();
                    if( (event.keyCode!=38)&&(event.keyCode!=38) ){
                        spinner.singleRun();
                    }
                }).blur(function(){
                    spinner.stop();
                });
                
                $scope.$watch('output',function(newVal){
                    element.val(newVal);
                });
                
                if (attr['ngDisabled']) {
                    var methodName = attr['ngDisabled'];
                    $scope.$parent.$watch(methodName, function(newVal, oldVal){
                        if(newVal){
                            element.attr('disabled','disabled').addClass('zixys-disabled-input');
                        }else {
                            element.removeAttr('disabled').removeClass('zixys-disabled-input');
                        }
                    });
                }
                
            }
        }
    })
    
    .directive('colorpick',['Colors', function(Colors){
        return {
            restrict: 'A',
            replace: true,
            template:'<span>\n\
                        <input type="text" class="zixys-colorpicker">\n\
                        <span class="zixys-color-prev" percentslider="output.alpha">\n\
                            <b></b>\n\
                        </span>\n\
                    </span>',
            scope: {
                output:'=colorpick'
            },
            link:function($scope, element, attr){
                var input = element.children('input'),
                    previewer = element.find('b');
                
                //defaults
                $scope.output = $.extend({
                    rgb:{
                        r:255,
                        g:255,
                        b:255
                    },
                    alpha:100
                },$scope.output);
                
                function setBackground(){
                    var value = 'rgba('+
                                    $scope.output.rgb.r+','+
                                    $scope.output.rgb.g+','+
                                    $scope.output.rgb.b+','+
                                    parseInt($scope.output.alpha)/100+')';

                    previewer[0].style.background = value;
                };
                
                input.ColorPicker({
                    onSubmit: function(hsb, hex, rgb, el) {
                        el.value = hex;
                        $(el).ColorPickerHide();
                        $scope.output.rgb = rgb;
                        setBackground();
                    },
                    onBeforeShow: function (picker) {
                        input.ColorPickerSetColor(this.value);
                    },
                    onChange : function(hsb, hex, rgb){
                        input[0].value=hex;
                        $scope.output.rgb = rgb;
                        $scope.$apply();
                        setBackground();
                    }
                }).bind('change keyup',function(){
                    input.ColorPickerSetColor(this.value);
                    $scope.output.rgb = Colors.HexToRGB(this.value);
                    setBackground();
                    $scope.$apply();
                }).val(Colors.RGBToHex($scope.output.rgb));
                
                $scope.$watch("output.alpha", function(newVal){
                    if(angular.isUndefined(newVal)) return;
                    setBackground();
                });

                $scope.$watch("output.rgb", function(newVal){
                    if(angular.isUndefined(newVal)) return;
                    input.val(Colors.RGBToHex(newVal));
                    setBackground();
                });

                var pickerId = input.data('colorpickerId');
                $('body>#'+pickerId).css('z-index','999999');
                
           }
        }
    }])
    .directive('percentslider',['$compile','$rootScope',function($compile,$rootScope){
        return {
            restrict: 'A',
            replace: false,
            scope: {
                output:'=percentslider'
            },
            link:function($scope, element, attr){

                var slider = '<div class="zixys-slider zixys-hidden" style="z-index:999999">\n\
                                <div class="zixys-slide-bg">\n\
                                    <b style="bottom:{{sliderValue}}%"></b>\n\
                                </div>\n\
                                <div class="zixys-slider-input"><input class="zixys-input zixys-spinner" min="0" max="100" ng-model="sliderValue" />%\n\
                                </div>\n\
                             </div>';
                
                slider = $compile(slider)($scope);
                slider.appendTo('body');
                var slideBtn = slider.find('b');
                var slideContainer = slideBtn.parent();
                var sliderInput = slider.find('input'); 
                var scale = slideContainer.height() - slideBtn.outerHeight();
                var doc = $(document);
                $scope.sliderValue = $scope.output || 100;
                
                element.click(function(event){
                    doc.trigger('click');
                    if(slider.hasClass('zixys-hidden')){
                        show();
                    }else{
                        hide();
                    }
                    event.stopPropagation();
                });
                
                function show (){
                    var position = element.offset();
                    slider.css({
                        left : position.left + element.width() + 10,
                        top : position.top - slider.height()/2 + element.height()/2
                    });
                    bindDraggables();
                    slider.removeClass('zixys-hidden');
                };
                
                function hide (){
                    unbindDraggables();
                    slider.addClass('zixys-hidden');
                };
                
 
                function mouseMove(event) {
                    var d = event.pageY - slideContainer.offset().top;
                               
                    if( d>scale){
                        d = scale;
                    }else if(d<0){
                        d = 0;
                    }

                    var val = parseInt((100*Math.abs(scale-d))/scale);
                    //$scope.pos = d;
                    $scope.sliderValue = val;
                    $scope.$apply();
                };
                
                function bindDraggables () {
                    doc.bind('mousedown.zixysSlider',function(event){
                        if(event.target === slideBtn[0] || event.target === slideContainer[0] ){
                            
                            doc.bind('mousemove.zixysSlider',mouseMove);
                            mouseMove(event);
                            // cancel out any text selections 
                            document.body.focus(); 
                            // prevent text selection in IE 
                            document.onselectstart = function () { return false; }; 
                            return false;
                        }
                    }).bind('mouseup.zixysSlider',function(event){
                        // we're done with these events until the next OnMouseDown 
                        document.onmousemove = undefined; 
                        document.onselectstart = undefined;
                        doc.unbind('mousemove.zixysSlider');
                    }).bind('click.zixysSlider',function(){
                        hide();
                    });                   
                };
                
                function unbindDraggables () {
                    doc.unbind('mousedown.zixysSlider','mousemove.zixysSlider','click.zixysSlider');
                }
                
                slider.bind('click.zixysSlider',function(e){
                    e.stopPropagation();
                });
                
                $scope.$watch('sliderValue',function(newVal,oldVal){
                    $scope.output = newVal;
                });
            }
        }
    }]);


angular.module('zixys.domSelector',[])

    .directive('zixysDomSelector', function() {

        return {
            restrict: 'C',
            scope: {},
            replace:true,
            //require: 'zixysMainCtrl',
            //controller: 'zixysMainCtrl',
            template:'<em id="zixys-select-button"><em></em></em>',

            link: function($scope, element, attrs) {
                var $selectedTag;
                
                var unpress = function(){
                    element.removeClass('zixys-sbutton-pressed');
                };
                
                var enableSelector = function(){
                    $(document).bind('mouseover.zixys',function(e){
                        var $this = $(e.target);
			if($this.closest('#zixys-wrap').length>0){
                            return;
                        };	
                        $this
                        .addClass('zixys-hovered-item')
                        .bind('mousedown.zixys mouseup.zixys',function(ev){
                            ev.stopImmediatePropagation();
                            ev.stopPropagation();
                            return false;
                        })
                        .bind('click.zixys',function(ev){
                            $selectedTag = $(ev.target);
                            
                            $scope.$root.$broadcast('beforeSelectElement',$selectedTag);
                            
                            element.removeClass('zixys-sbutton-pressed');
                            $selectedTag
                            .removeClass('zixys-hovered-item')
                            .unbind('mouseout.zixys mousedown.zixys click.zixys mouseup.zixys');
                            $(document).unbind('mouseover.zixys');
                            $scope.$root.$broadcast('selectElement',$selectedTag);
                            ev.stopImmediatePropagation();
                            ev.stopPropagation();
                            return false;				
                        })
                        .bind('mouseout.zixys',function(ev){
                            $(ev.target).removeClass('zixys-hovered-item')
                            .unbind('mouseup.zixys mouseout.zixys mousedown.zixys click.zixys');
                        });
				
                    });
                };                
                
                element.bind('click',function(e){
                    if(element.hasClass('zixys-sbutton-pressed')){
                        $(document).unbind('mouseover.zixys');
                        element.removeClass('zixys-sbutton-pressed');
                    }else{
                        //press
                        enableSelector();
                        element.addClass('zixys-sbutton-pressed');
                    }
                });
            }
        }
        
    })
    
    .run(['$rootScope','$compile', function($rootScope,$compile){
        $rootScope.$on('zixysDomReady',function(event,params){
            $rootScope.addButton('DOM Selector','zixys-dom-selector',$compile);
        });

    }]);
    
    
angular.module('zixys.gradient',[])
    
    .directive('zixysPresets',["gradientPresets", "gradient", function(gradientPresets, gradient){
        return {
            restrict: 'C',
            replace: true,
            template : '<div ><input id="zixys-presets" type="button" value="Presets" /><div id="zixys-preset-window"></div></div>',
            scope: {
                output:"=zixysPresets"
            },
            link:function($scope, element, attrs){
                
                var win = element.find('#zixys-preset-window'),
                    button = element.find('#zixys-presets');
                
                function open() {
                    win.show();
                };

                function close() {
                    win.hide();
                };
                
                function addPreset(background, id){
                    $('<div class="zixys-preset-sample"></div>')
                        .attr('style',background)
                        .click(function(){
                            if(!gradientPresets.deployed[id]){
                                gradientPresets.deployed[id] = gradientPresets.deploySet(gradientPresets.defaults[id]);
                            }
                            $scope.$emit('gradient.presetLoaded',gradientPresets.deployed[id]);
                        })
                        .appendTo(win);
                }
                
                for(var i=0; i<gradientPresets.defaults.length; i++){
                    addPreset( gradient.getCssCode("-45deg,"+gradientPresets.defaults[i]), i );
                }
                
                button.click(function(e){
                   open();
                   e.stopPropagation();
                });
                
                $(document).click(function(){
                   close(); 
                });
            }
        }
    }])

    .directive('colorMarkers',['$compile',function($compile){
        return {
            restrict: 'A',
            replace: true,
            template:'<div>'+
                        '<div class="zixys-menu-gpreview-wrap">'+
                            '<div id="zixys-gradient-scroller"></div>'+
                         '</div>'+
                         '<div class="zixys-menu-block">'+
                            '<div class="zixys-input-box"><span class="zixys-menu-label">color</span><input class="color-picker" colorpick="markerColor"></div>'+
                            '<div class="zixys-input-box"><span class="zixys-menu-label">position(%)</span><input class="zixysSpinner" min="0" max="100" ng-disabled="markDisable" ng-model="position" type="text"></div>'+
                            '<div class="zixys-input-box"><input id="zixys-remove-marker" ng-disabled="markDisable" ng-click="removeMarker()" type="button" value="remove" ></div>'+
                         '</div>'+
                     '</div>',
            scope: {
                output: '=colorMarkers'
            },
            link:function($scope, element, attr){
                var previewer = element.find('#zixys-gradient-preview'),
                    pad = element.find('#zixys-gradient-scroller'),
                    markers = [],
                    lastSelectedMarker,
                    previewsMarkerCount;
                $scope.output = markers;
                $scope.markDisable = true;
 
                function sortMarkers() {
                    var tmp;
                    for(var i=0; i<markers.length; i++){
                        for(var j=0; j<markers.length; j++){
                            if(markers[j+1] && (markers[j].output.position > markers[j+1].output.position)){
                                tmp = markers[j+1];
                                markers[j+1] = markers[j];
                                markers[j] = tmp;
                            }
                        }
                    };
                }
                
                function getPriorMarkersLength(marker){
                    var sum=0;
                    for(var i=0; i<markers.length; i++){
                        //checking nearness [+0.5,-0.5]
                        if( (markers[i] != marker) && (marker.output.position-0.5<markers[i].output.position) && (marker.output.position+0.5>markers[i].output.position )){
                            sum++;
                        }
                    }
                    return sum;
                }

                function checkMarkersPosition(marker) {
                    sortMarkers();
                };

                function removeAllMarkers() {
                    for(var i=0; i<markers.length; i++){
                        markers[i].removeNode();
                    }
                    markers.length=0;
                    lastSelectedMarker = null;
                    $scope.markDisable = true;
                    $scope.position = 0;
                };                

                $scope.removeMarker = function() {
                    for(var i=0; i<markers.length; i++){
                        if (lastSelectedMarker === markers[i]) {
                            markers[i].removeNode();
                            markers.splice(i,1);
                            lastSelectedMarker = null;
                            $scope.markDisable = true;
                            $scope.position = 0;
                            $scope.$emit('gradient.markerChange');
                            break;
                        }
                    }
                };

                pad.click(function(event){
                    if(event.target === pad[0]){
                        var marker = new zixysMarker(pad, event.pageX, $scope);
                        markers.push(marker);
                        sortMarkers();
                        $scope.$broadcast('markerSelected', marker);
                        $scope.$emit('gradient.markerChange');
                    }
                });
                
                $scope.$on('markerSelected',function(event,marker){
                    if(lastSelectedMarker != marker){
                        lastSelectedMarker ? lastSelectedMarker.deactivate() : null;
                        marker.activate();
                        lastSelectedMarker = marker;
                        markerCount = previewsMarkerCount = getPriorMarkersLength(marker);
                        $scope.markDisable = false;
                        $scope.position = marker.output.position;
                        $scope.markerColor.rgb = marker.output.rgb;
                        $scope.markerColor.alpha = marker.output.alpha;
                        $scope.$apply();
                    }
                })
                
                $scope.$watch('markerColor',function(newVal,oldVal){
                    if(newVal && lastSelectedMarker){
                        lastSelectedMarker.output.rgb = newVal.rgb;
                        lastSelectedMarker.output.alpha = newVal.alpha;
                        $scope.$emit('gradient.markerChange');
                    }
                },true);
                
                $scope.$on('markerMove',function(event, pos){
                    $scope.position = pos;
                    $scope.$apply();
                    checkMarkersPosition(lastSelectedMarker);
                    $scope.$emit('gradient.markerChange');
                });
                
                $scope.$watch('position',function(newVal,oldVal){
                    if(newVal && lastSelectedMarker){
                        lastSelectedMarker.setPosition(parseInt(newVal));
                        checkMarkersPosition(lastSelectedMarker);
                        $scope.$emit('gradient.markerChange');
                    }
                });
                
                $scope.output.loadPreset = function(markersArr){
                    removeAllMarkers();
                    for(var i=0; i<markersArr.length; i++){
                        var marker = new zixysMarker(pad, 0, $scope);
                        marker.setPosition(markersArr[i].position);
                        marker.setColor(markersArr[i].rgb, markersArr[i].alpha);
                        markers.push(marker);
                    };
                    sortMarkers();
                    $scope.$emit('gradient.markerChange');
                }
                
            }
        }
    }])

    .service('gradientPresets',['$rootScope','Colors', 'gradient', function($rootScope, Colors, gradient){
            
	this.defaults = [
	'#cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%',
	'#4c4c4c 0%, #595959 12%, #666666 25%, #474747 39%, #2c2c2c 50%, #000000 51%, #111111 60%, #2b2b2b 76%, #1c1c1c 91%, #131313 100%',
	'#87e0fd 0%, #53cbf1 40%, #05abe0 100%',
	'#f0f9ff 0%, #cbebff 47%, #a1dbff 100%',
	'#7abcff 0%, #60abf8 44%, #4096ee 100%',
	'#00b7ea 0%, #009ec3 100%',
	'#88bfe8 0%, #70b0e0 100%',
	'#feffff 0%, #ddf1f9 35%, #a0d8ef 100%',
	'#b8e1fc 0%, #a9d2f3 10%, #90bae4 25%, #90bcea 37%, #90bff0 50%, #6ba8e5 51%, #a2daf5 83%, #bdf3fd 100%',
	'#3b679e 0%, #2b88d9 50%, #207cca 51%, #7db9e8 100%',
	'#6db3f2 0%, #54a3ee 50%, #3690f0 51%, #1e69de 100%',
	'#ebf1f6 0%, #abd3ee 50%, #89c3eb 51%, #d5ebfb 100%',
	'#e4f5fc 0%, #bfe8f9 50%, #9fd8ef 51%, #2ab0ed 100%',
	'#cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%',
	'#a7c7dc 0%, #85b2d3 100%',
	'#3f4c6b 0%, #3f4c6b 100%',
	'#d0e4f7 0%, #73b1e7 24%, #0a77d5 50%, #539fe1 79%, #87bcea 100%',
	'#e1ffff 0%, #e1ffff 7%, #e1ffff 12%, #fdffff 12%, #e6f8fd 30%, #c8eefb 54%, #bee4f8 75%, #b1d8f5 100%',
	'#b3dced 0%, #29b8e5 50%, #bce0ee 100%',
	'#d5cea6 0%, #c9c190 40%, #b7ad70 100%',
	'#f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%',
	'#a90329 0%, #8f0222 44%, #6d0019 100%',
	'#fefcea 0%, #f1da36 100%',
	'#b4ddb4 0%, #83c783 17%, #52b152 33%, #008a00 67%, #005700 83%, #002400 100%',
	'#cdeb8e 0%, #a5c956 100%',
	'#c9de96 0%, #8ab66b 44%, #398235 100%',
	'#f8ffe8 0%, #e3f5ab 33%, #b7df2d 100%',
	'#a9db80 0%, #96c56f 100%',
	'#b4e391 0%, #61c419 50%, #b4e391 100%',
	'#9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%',
	'#e6f0a3 0%, #d2e638 50%, #c3d825 51%, #dbf043 100%',
	'#bfd255 0%, #8eb92a 50%, #72aa00 51%, #9ecb2d 100%',
	'#eeeeee 0%, #cccccc 100%',
	'#cedce7 0%, #596a72 100%',
	'#606c88 0%, #3f4c6b 100%',
	'#b0d4e3 0%, #88bacf 100%',
	'#f2f5f6 0%, #e3eaed 37%, #c8d7dc 100%',
	'#d8e0de 0%, #aebfbc 22%, #99afab 33%, #8ea6a2 50%, #829d98 67%, #4e5c5a 82%, #0e0e0e 100%',
	'#b5bdc8 0%, #828c95 36%, #28343b 100%',
	'#b8c6df 0%, #6d88b7 100%',
	'#cfe7fa 0%, #6393c1 100%',
	'#d2dfed 0%, #c8d7eb 26%, #bed0ea 51%, #a6c0e3 51%, #afc7e8 62%, #bad0ef 75%, #99b5db 88%, #799bc8 100%',
	'#e2e2e2 0%, #dbdbdb 50%, #d1d1d1 51%, #fefefe 100%',
	'#f2f6f8 0%, #d8e1e7 50%, #b5c6d0 51%, #e0eff9 100%',
	'#d4e4ef 0%, #86aecc 100%',
	'#f5f6f6 0%, #dbdce2 21%, #b8bac6 49%, #dddfe3 80%, #f5f6f6 100%',
	'#f3e2c7 0%, #c19e67 50%, #b68d4c 51%, #e9d4b3 100%',
	'#f9fcf7 0%, #f5f9f0 100%',
	'#c3d9ff 0%, #b1c8ef 41%, #98b0d9 100%',
	'#d2ff52 0%, #91e842 100%',
	'#fefefd 0%, #dce3c4 42%, #aebf76 100%',
	'#e4efc0 0%, #abbd73 100%',
	'#a4b357 0%, #75890c 100%',
	'#627d4d 0%, #1f3b08 100%',
	'#ffaf4b 0%, #ff920a 100%',
	'#fac695 0%, #f5ab66 47%, #ef8d31 100%',
	'#ffc578 0%, #fb9d23 100%',
	'#fceabb 0%, #fccd4d 50%, #f8b500 51%, #fbdf93 100%',
	'#ffa84c 0%, #ff7b0d 100%',
	'#ffb76b 0%, #ffa73d 50%, #ff7c00 51%, #ff7f04 100%',
	'#ff5db1 0%, #ef017c 100%',
	'#fb83fa 0%, #e93cec 100%',
	'#e570e7 0%, #c85ec7 47%, #a849a3 100%',
	'#cb60b3 0%, #ad1283 50%, #de47ac 100%',
	'#fcecfc 0%, #fba6e1 50%, #fd89d7 51%, #ff7cd8 100%',
	'#cb60b3 0%, #c146a1 50%, #a80077 51%, #db36a4 100%',
	'#ebe9f9 0%, #d8d0ef 50%, #cec7ec 51%, #c1bfea 100%',
	'#febbbb 0%, #fe9090 45%, #ff5c5c 100%',
	'#f2825b 0%, #e55b2b 50%, #f07146 100%',
	'#ff3019 0%, #cf0404 100%',
	'#f85032 0%, #f16f5c 50%, #f6290c 51%, #f02f17 71%, #e73827 100%',
	'#feccb1 0%, #f17432 50%, #ea5507 51%, #fb955e 100%',
	'#efc5ca 0%, #d24b5a 50%, #ba2737 51%, #f18e99 100%',
	'#f3c5bd 0%, #e86c57 50%, #ea2803 51%, #ff6600 75%, #c72200 100%',
	'#b7deed 0%, #71ceef 50%, #21b4e2 51%, #b7deed 100%',
	'#e0f3fa 0%, #d8f0fc 50%, #b8e2f6 51%, #b6dffd 100%',
	'#feffe8 0%, #d6dbbf 100%',
	'#fcfff4 0%, #e9e9ce 100%',
	'#fcfff4 0%, #dfe5d7 40%, #b3bead 100%',
	'#e5e696 0%, #d1d360 100%',
	'#7d7e7d 0%, #0e0e0e 100%',
	'#959595 0%, #0d0d0d 46%, #010101 50%, #0a0a0a 53%, #4e4e4e 76%, #383838 87%, #1b1b1b 100%',
	'#aebcbf 0%, #6e7774 50%, #0a0e0a 51%, #0a0809 100%',
	'#c5deea 0%, #8abbd7 31%, #066dab 100%',
	'#f7fbfc 0%, #d9edf2 40%, #add9e4 100%',
	'#d6f9ff 0%, #9ee8fa 100%',
	'#e9f6fd 0%, #d3eefb 100%',
	'#63b6db 0%, #309dcf 100%',
	'#a9e4f7 0%, #0fb4e7 100%',
	'#93cede 0%, #75bdd1 41%, #49a5bf 100%',
	'#b2e1ff 0%, #66b6fc 100%',
	'#deefff 0%, #98bede 100%',
	'#feffff 0%, #d2ebf9 100%',
	'#a7cfdf 0%, #23538a 100%',
	'#ffffff 0%, #f1f1f1 50%, #e1e1e1 51%, #f6f6f6 100%',
	'#f6f8f9 0%, #e5ebee 50%, #d7dee3 51%, #f5f7f9 100%',
	'#F2F6F8 0%, #D8E1E7 50%, #B5C6D0 51%, #E0EFF9 100%',
	'#f6e6b4 0%, #ed9017 100%',
	'#eab92d 0%, #c79810 100%',
	'#ffd65e 0%, #febf04 100%',
	'#f1e767 0%, #feb645 100%'];
        
        this.deployed = {};

        this.parseHexColorStop = function(input){
            input = input.match(/(\w+)/gi);
            return {
                rgb:Colors.HexToRGB(input[0]),
                position:input[1],
                alpha:100
            };
        }

        this.parseRGBAColorStop = function(input){
            var color = input.match(/\((.+)\)/)[1].split(','),
                alpha = color.pop(),
                position = input.replace(/rgba\((.+)\)/,'');
            return {
                rgb : {
                    r : parseInt(color[0]),
                    g : parseInt(color[1]),
                    b : parseInt(color[2])
                },
                alpha : parseInt(alpha)*100,
                position : position
            };
        }

        this.parseRGBColorStop = function(input){
            var color = input.match(/\((.+)\)/)[1].split(','),
                position = input.replace(/rgb\((.+)\)/,'');
            return {
                rgb : {
                    r : parseInt(color[0]),
                    g : parseInt(color[1]),
                    b : parseInt(color[2])
                },
                alpha : 100,
                position : position
            };
        }

        this.deployColorStop = function(colorStop){
            if(colorStop.match('#')){
                //hex color
                return this.parseHexColorStop(colorStop);
            }else 
            if(colorStop.match('rgba')){
                //rgba
                return this.parseRGBAColorStop(colorStop);
            }else
            if(colorStop.match('rgb')){
                //rgb
                return this.parseRGBColorStop(colorStop);
            }
        }
        
        this.deploySet = function(colorSet) {
            var set = colorSet.split(',');
            for(var i=0; i<set.length; i++){
                set[i] = this.deployColorStop(set[i]);
            }
            return set;
        };
        
        //TODO:: parse native gradient values
        this.parseNativeCssGradient = function(nativeCss){
            var linearGrad = nativeCss.match(/\((.+)\)/); //returns "left, rgba(255,255,255,1) 0%, rgba(112,17,112,1) 100%";
            linearGrad = linearGrad ? linearGrad[1] : '';
            
            var angle = linearGrad.match(/(\w+\s*\w*),/) // returns "left"|"left top"|"45deg""
            angle = angle ? angle[1] : '';
            
            var colorStops = linearGrad.replace(/,(?=\s*(rgb|#))/g,';').split(';');
            colorStops.shift();
            
            if(angle.length>0){
                console.log(angle);
            }
        };


    }])
    
    .service('gradient',['$rootScope','style',function($rootScope,style){
        var context,$canvas, pageWidth, pageHeight, elementWidth, elementHeight, gradientStarted, self = this;
        var $body = $('body'), $preview = $('#zixys-gradient-tab #zixys-gradient-preview');
        this.started = false;
        this.$body = $body;
        this.$preview = $preview;
        this.selectedElement;
        
        $rootScope.$on('selectElement',function(event,element){
            self.selectedElement = element;
        });
        
        function createCanvas (){
            $body.append('<div id="gCanvasWrap" style="position:absolute; top:0; left:0; width:'+pageWidth+'px; height:'+pageHeight+'px;"><canvas id="gCanvas" width="'+pageWidth+'px" height="'+pageHeight+'px"></canvas></div>');
            $canvas = $body.children('#gCanvasWrap').children('#gCanvas');
            context = $canvas[0].getContext("2d");
            context.clearRect(0,0,pageWidth,pageHeight);
        };

        function destroyCanvas () {
            $canvas.remove();
            $body.children('#gCanvasWrap').remove();
        };	
        
        function line (x0,y0,x1,y1) {
            context.beginPath();
            context.moveTo(x0,y0);
            context.lineTo(x1,y1);
            context.stroke();
        };

        function refreshSelectors (){
            pageWidth = $body.outerWidth();
            pageHeight = $body.outerHeight();
            elementWidth = self.selectedElement.outerWidth();
            elementHeight = self.selectedElement.outerHeight();
        };

        function transformToNumbers(object) {
            for(k in object){
                object[k] = parseFloat(object[k]);
            }
        }

        this.startLine = function (x,y) {
            createCanvas();
            $body.bind('mousemove.zixys',function(event){
                context.clearRect(0,0,pageWidth,pageHeight);
                line(x,y,event.pageX,event.pageY);			
            });
        };

        this.endLine = function() {
            $body.unbind('mousemove.zixys');
            destroyCanvas();
        };
        
        this.getGradientLineData = function(p0,p1){
            var a,b,c,angle,kp,kr,kg,mg,r;
            var quadrant;
            /****************** math part *****************/
            function calcQuadrant1(){
                angle = - Math.asin(b/c) *(180/3.14) + 360;

                //--- calc Xr, Yr ---
                Xr = kp/(mg + 1/mg);
                Yr = mg*Xr;
                //-----------------------
                //
                //--- calculate
                r = Math.sqrt(Xr*Xr + Yr*Yr);
            //------------------
            };
		
            function calcQuadrant2 (){
                angle = Math.asin(b/c)*(180/3.14)+180 ;
			
                //--- calc kr -----
                kr = - mg*elementWidth;
                //------------------
			
                //--- calc Xr, Yr ---
                Xr = (kp-kr)/(mg + 1/mg);
                Yr = mg*Xr + kr;
                //-----------------------
			
                //--- calculate R!!! ---
                r = Math.sqrt((elementWidth - Xr)*(elementWidth - Xr) + Yr*Yr);
            //------------------------
            };

            function calcQuadrant3 (){
                angle = Math.asin(b/c) *(180/3.14)+180;
			
                //--- calc kr -----
                kr = elementHeight - mg*elementWidth;
                //------------------
			
                //--- calc Xr, Yr ---
                Xr = (kp-kr)/(mg + 1/mg);
                Yr = mg*Xr + kr;
                //-----------------------
			
                //--- calculate R!!! ---
                r = Math.sqrt((elementWidth - Xr)*(elementWidth - Xr) + (elementHeight-Yr)*(elementHeight-Yr));
            //------------------------
			
            };

            function calcQuadrant4 (){
                angle = - Math.asin(b/c) *(180/3.14);
			
                //--- calc kr -----
                kr = elementHeight;
                //------------------
			
                //--- calc Xr, Yr ---
                Xr = (kp-kr)/(mg + 1/mg);
                Yr = mg*Xr + kr;
                //-----------------------
			
                //--- calculate R!!! ---
                r = Math.sqrt( Xr*Xr + (elementHeight-Yr)*(elementHeight-Yr));
            //------------------------
            };

            var _b = p1.y - p0.y;
            var _a = p1.x - p0.x;

			
            b = p1.y - p0.y;
            a = p1.x - p0.x;
            c = Math.sqrt( a*a + b*b );
			
            //----- calc Yg ----
            mg = b/a;
            kg = -p0.x * (b/a) + p0.y;
            //----------------
			
            //---- calc Yp ----
            kp = p0.y + (1/mg)*p0.x;
            //-------------------
			
            //-----  find quadrant -------
            if(_a>0 && _b>0){
                //1st
                calcQuadrant1();
                quadrant = 1;
            }else
            if(_a<0 && _b>0){
                //2nd
                calcQuadrant2();
                quadrant = 2;
            //quadrant = 90;
            }else
            if(_a<0 && _b<0){
                //3rd
                calcQuadrant3();
                quadrant = 3;
            //quadrant = 180;
            }else
            if(_a>0 && _b<0){
                //4th
                calcQuadrant4();
                quadrant = 4;
            //quadrant = 270;
            }else{

                if(_a==0 && b==0){
                    return;
                };
				
                if(_a==0){
                    if(b>0){
                        r=p0.y;
                        angle=270;
                    }else{
                        r = elementHeight - p0.y;
                        angle=90;
                    }
                }else
                if(b==0 ){
                    if(a>0){
                        r=p0.x;
                        angle=0;
                    }else{
                        r = elementWidth - p0.x;
                        angle=180;
                    }
                }
            }
            return {
                distance:r,
                length:c,
                angle:angle,
                quadrant:quadrant
            }
        };
        /*******************************************/
        
        this.getClickCoordinates = function(event, selectedElement){
            if(!selectedElement){
                return;
            }
			
            refreshSelectors();
            
            var output = {
                page : {
                    x : event.pageX,
                    y : event.pageY
                },
                element : {
                    x : event.pageX - selectedElement.offset().left,
                    y : event.pageY - selectedElement.offset().top                    
                }
            }
            
            return output;
        };
        
        function stringifyRGBA (color) {
            return 'rgba('+color.rgb.r+','+color.rgb.g+','+color.rgb.b+','+parseInt(color.alpha)/100+')';
        }
        
        function stringifyMarkersAbsolute (markers) {
            var output = '';
            for(var i=0; i<markers.length; i++){
                output = output + stringifyRGBA(markers[i].output)+' '+markers[i].output.position+'%,';
            }
            return output;
        }        

        function stringifyMarkersRelative (markers,positionData) {
            var output = '';
            for(var i=0; i<markers.length; i++){
                output = output + 
                         stringifyRGBA(markers[i].output)+' '+
                         (positionData.distance + (markers[i].output.position * positionData.length)/100)+'px,';
                     //  (r+(gr.markers[i].getPos()*c)/100)
            }
            return output;
        }

        this.getCssCode = function(codeLine) {
            return  'background-image: linear-gradient('+codeLine+');'+ /* W3C */
                    'background-image: -o-linear-gradient('+codeLine+');'+ /* Opera 11.10+ */
                    'background-image: -moz-linear-gradient('+codeLine+');'+ /* FF3.6+ */
                    'background-image: -webkit-linear-gradient('+codeLine+');'+ /* Chrome10+,Safari5.1+ */
                    'background-image: -ms-linear-gradient('+codeLine+');';	/* IE10+ */        
        }

        this.setPreview = function(from, to, markers) {
            var codeLine = 'left, '+
                           stringifyRGBA(from)+' 0%, '+
                           stringifyMarkersAbsolute(markers)+
                           stringifyRGBA(to)+' 100%';
            
            $preview.attr('style', this.getCssCode(codeLine));
        };
        
        this.applyManualGradient = function(positionData, from, to, markers){
            transformToNumbers(positionData);
            var codeLine = positionData.angle+'deg, '+
                           stringifyRGBA(from) +' '+ positionData.distance+'px, '+
                           stringifyMarkersRelative(markers, positionData)+
                           stringifyRGBA(to) +' '+ (positionData.distance + positionData.length)+'px';
                       
            style.set(this.selectedElement,'gradient',this.getCssCode(codeLine));
        }

        this.applyAutoGradient = function(positionData, from, to, markers){
            transformToNumbers(positionData);
            var codeLine = positionData.angle+'deg, '+
                           stringifyRGBA(from) +' '+ '0%, '+
                           stringifyMarkersAbsolute(markers)+
                           stringifyRGBA(to) +' '+ ' 100%';
                       
            style.set(this.selectedElement,'gradient',this.getCssCode(codeLine));
        }

    }])

    .directive('gradientTab',function(){
        return {
            restrict: 'C',
            replace: false,
            template:							
                '<div id="zixys-gradient-tab" ng-controller="gradientCtrl">'+
                        '<div class="zixys-menu-block">'+
                        '<div class="zixys-input-box"><span class="zixys-menu-label">from</span><input class="color-picker" colorpick="gradientFrom" ng-model="from"></div>'+
                        '<div class="zixys-input-box"><span class="zixys-menu-label">to</span><input class="color-picker" colorpick="gradientTo" ng-model="to"></div>'+
                        '<div class="zixys-input-box">'+
                                '<em class="drawButton" zixys-button="drawButton" ></em>'+
                                '<label for="zixys-mode-manual" class="zixys-radio-label-first">manual</label>'+
                                '<input id="zixys-mode-manual" ng-model="mode" value="manual" ng-change="switchMode()" type="radio" >'+
                                '<label for="zixys-mode-auto" class="zixys-radio-label">auto</label>'+
                                '<input id="zixys-mode-auto" ng-model="mode" value="auto" ng-change="switchMode()" type="radio" >'+
                        '</div>'+
                        '</div>'+
                        '<div class="zixys-menu-block">'+
                                '<div class="zixys-input-box"><span class="zixys-menu-label">length</span><input ng-model="length" ng-disabled="isAuto" class="zixys-spinner" type="text"></div>'+
                                '<div class="zixys-input-box"><span class="zixys-menu-label">distance</span><input ng-model="distance" ng-disabled="isAuto" class="zixys-spinner" type="text"></div>'+
                                '<div class="zixys-input-box"><span class="zixys-menu-label">angle(deg)</span><input ng-model="angle" class="zixys-spinner" type="text"></div>'+
                        '</div>'+
                        '<div class="zixys-previewer">'+
                            '<div id="zixys-gradient-preview"></div>'+
                        '</div>'+
                        '<div color-markers="markers"></div>'+
                        '<div class="zixys-template-action zixys-presets">'+
                            
                        '</div>'+
                '</div>',


            link: function($scope, element, attrs) {
                
            }
        }
    })
    
    .controller('gradientCtrl',['$scope','dataStorage','gradient','gradientPresets',function($scope, dataStorage, gradient, gradientPresets){
       
        var p0,p1;
        
        gradient.$body.bind('click.zixys',function(event){
            
            if(!gradient.selectedElement || !$scope.drawButton.isPressed() ) return;
            
            var gradientData;
            if(!gradient.started){
                p0 = gradient.getClickCoordinates(event,gradient.selectedElement);
                gradient.startLine(p0.page.x,p0.page.y);
                gradient.started = true;
            }else{
                p1 = gradient.getClickCoordinates(event,gradient.selectedElement);
                gradient.endLine();
                gradientData = gradient.getGradientLineData(p0.element,p1.element);
                if(gradientData) {
                    $scope.length = parseInt(gradientData.length);
                    $scope.distance = parseInt(gradientData.distance);
                    $scope.angle = parseInt(gradientData.angle);
                    $scope.$apply();
                    $scope.drawButton.release();
                };
                
                gradient.started = false;
            }
        });
        
        function watchColors (newVal, oldVal){
            if(newVal){
                gradient.setPreview($scope.gradientFrom, $scope.gradientTo, $scope.markers);
                draw();
            }            
        };
        
        function draw (){
            if( !gradient.selectedElement || 
                !$scope.gradientFrom || 
                !$scope.gradientTo || 
                isNaN(parseInt($scope.angle))
            ) return;
            
            if( $scope.mode === "manual" ){
                if( !$scope.length || !$scope.distance) return;
                
                gradient.applyManualGradient({
                    "length" : $scope.length,
                    "distance" : $scope.distance,
                    "angle" : $scope.angle
                }, $scope.gradientFrom, $scope.gradientTo, $scope.markers);
            } else {
                gradient.applyAutoGradient({
                    "length" : $scope.length,
                    "distance" : $scope.distance,
                    "angle" : $scope.angle
                }, $scope.gradientFrom, $scope.gradientTo, $scope.markers);
            }
        };
        
        $scope.$watch('length',draw);
        $scope.$watch('distance',draw);
        $scope.$watch('angle',draw);
        
        $scope.$watch('gradientFrom',watchColors,true);
        $scope.$watch('gradientTo',watchColors,true);
        $scope.$on('gradient.markerChange',function(event){
            gradient.setPreview($scope.gradientFrom, $scope.gradientTo, $scope.markers);
            draw();
        });

        $scope.$on('gradient.presetLoaded',function(event, markers){
            $scope.gradientFrom = markers[0];
            $scope.gradientTo = markers[markers.length-1];
            $scope.markers.loadPreset(markers.slice(1,markers.length-1));
            $scope.$apply();
        });

        $scope.switchMode = function(){
            if( $scope.mode === "manual"){
                $scope.drawButton.enable();
                $scope.isAuto = false;
            }else{
                $scope.length = '';
                $scope.distance = '';
                $scope.angle = 0;
                $scope.drawButton.disable();
                $scope.isAuto = true;
            }
            draw();
        };
        
        $scope.mode = 'auto';
        $scope.drawButton = {
            iconClass:'zixys-gradient',
            initStateDisabled:true
        }
        $scope.isAuto = true;
        $scope.angle = 0;
        
        
    }])

    .run(['$rootScope','$compile',function($rootScope,$compile){
        
        $rootScope.$on('zixysDomReady',function(event,params){
            $rootScope.addTab('Gradient','gradient-tab',$compile);
        });
        
    }]);
    
    'use strict';

var zixysMarker = function(pad,pageX,$scope){
    this.pad = pad;
    this.$scope = $scope;
    this.node = $('<div class="zixys-marker">\n\
                     <div class="zixys-marker-color"></div>\n\
                  </div>');
    this.handle = this.node.children();
    this.doc = $(document);
    this.bindDraggables();
    this.pad.append(this.node);
    this.scale = this.pad.innerWidth();
    this.output = {
        position: this.calcRelativePosition(pageX),
        rgb:{
            r:0,
            g:0,
            b:0
        },
        alpha:100
    };
};

zixysMarker.prototype.calcRelativePosition = function(cursorX){
    this.d = cursorX - this.pad.offset().left;

    if( this.d>this.scale){
        this.d = this.scale;
    }else if(this.d<0){
        this.d = 0;
    }
    return parseInt((100*Math.abs(this.d))/this.scale);
}

zixysMarker.prototype.bindDraggables = function() {
    var self = this, pos;
    
    var mouseMove = function(event){
        pos = self.calcRelativePosition(event.pageX);
        self.setPosition( pos );
        self.$scope.$broadcast('markerMove', pos);
    }
    
    this.doc.bind('mousedown.zixysMarker',function(event){
        if(event.target === self.handle[0]){
            self.doc.bind('mousemove.zixysMarker',mouseMove);
            self.$scope.$broadcast('markerSelected',self);
            // cancel out any text selections 
            document.body.focus();
            // prevent text selection in IE 
            document.onselectstart = function () {
                return false;
            };
            return false;
        }
    }).bind('mouseup.zixysSlider',function(event){
        // we're done with these events until the next OnMouseDown 
        document.onmousemove = undefined; 
        document.onselectstart = undefined;
        self.doc.unbind('mousemove.zixysMarker');
    });
};

zixysMarker.prototype.setPosition = function (pos) {
    this.output.position = pos;
    this.node[0].style.left = pos+'%';
};

zixysMarker.prototype.setColor = function (rgb, alpha) {
    this.output.rgb = rgb;
    this.output.alpha = alpha;
};

zixysMarker.prototype.activate = function () {
    this.node.addClass('zixys-selected-marker');
};

zixysMarker.prototype.deactivate = function () {
    this.node.removeClass('zixys-selected-marker');
};

zixysMarker.prototype.removeNode = function () {
    this.node.remove();
}

angular.module('zixys.services',[])

    .service('dataStorage',['$rootScope',function($rootScope){
        var storage, element, zid, self = this;
        //create storage Object
        if(!$rootScope.storage){
            $rootScope.storage = {};
            storage = $rootScope.storage;
        }

        $rootScope.$on('beforeSelectElement',function(event,elem){
            element = elem;
            zid = element.attr('zid');

            if(!zid) {
                zid = new Date().getTime();
                element.attr('zid',zid);
                self.save('attributes','style', element.attr('style') );
            }
        });
        
        var checkExistance = function(_zid,category){
            if(!$rootScope.storage[_zid]){
                $rootScope.storage[_zid] = {
                    $element : element
                };
            }
            if(!$rootScope.storage[_zid][category]){
                $rootScope.storage[_zid][category] = {};
            }
        }
        
        this.save = function(domain,property,value){
            checkExistance(zid,domain);
            $rootScope.storage[zid][domain][property] = value;
        }
        
        this.load = function(domain,property){
            if(!zid) return;
            if(property){
                return $rootScope.storage[zid][domain][property];
            }
            return $rootScope.storage[zid][domain];
        }
    }])

    .service('style',['dataStorage',function(dataStorage){
        
        this.set = function(element,name,value){
            dataStorage.save('style',name,value);
            var nativeStyle = dataStorage.load('attributes','style');
            var styles = dataStorage.load('style');
            var css = nativeStyle || '';
            
            for(var k in styles) {
                css = css + styles[k];
            }
            //console.log(css);
            element.attr('style',css);
        }
        
    }])

    .service('Colors',function(){
        
        this.HexToRGB = function(hex) {
            var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
            return {
                r: hex >> 16, 
                g: (hex & 0x00FF00) >> 8, 
                b: (hex & 0x0000FF)
            };
        };
                
        this.RGBToHex = function(rgb) {
            function toHex(input) {
                if(input.toString(16).length<2){
                    return '0'+input.toString(16);
                }
                return input.toString(16);
            }
            return toHex(rgb.r)+toHex(rgb.g)+toHex(rgb.b);
        };
    });
    
    
angular.module('zixys.shadow',[])
    
    .directive('shadowTab',function(){
        return {
            restrict: 'C',
            replace: false,
            template:							
                    '<div id="zixys-shadow-tab" ng-controller="shadowCtrl">'+
                            '<div class="zixys-menu-block">'+
                                    '<div class="zixys-input-box"><span class="zixys-menu-label">top</span><input class="zixys-spinner" ng-model="shadow.top" ng-disabled="disable" type="text"></div>'+
                                    '<div class="zixys-input-box"><span class="zixys-menu-label">left</span><input class="zixys-spinner" ng-model="shadow.left" ng-disabled="disable" type="text"></div>'+
                                    '<div class="zixys-input-box"><span class="zixys-menu-label">blur</span><input class="zixys-spinner" min="0" ng-model="shadow.blur" ng-disabled="disable" type="text"></div>'+
                            '</div>'+
                            '<div class="zixys-menu-block">'+
                                    '<div class="zixys-input-box"><span class="zixys-menu-label">size</span><input class="zixys-spinner" ng-model="shadow.size" ng-disabled="disable" type="text"></div>'+
                                    '<div class="zixys-input-box"><span class="zixys-menu-label">color</span><input colorpick="shadow.color"  type="text" ng-disabled="disable" ></div>'+
                                    '<div class="zixys-input-box"><span class="zixys-menu-label">inner</span><input ng-model="shadow.inner" type="checkbox" ng-disabled="disable" ></div>'+
                            '</div>'+
                            '<div class="zixys-menu-block">'+
                                    '<div class="zixys-input-box"><input type="button" ng-click="addShadow()" value="Add Shadow" id="zixis-sh-addShadow" ng-disabled="disableAdd"  /></div>'+
                                    '<div class="zixys-input-box"><span class="zixys-menu-label">shadow</span ng-model="shadows" >'+
                                        '<select ng-disabled="disable" ng-change="selectShadow()" ng-model="selected" ng-options="s.index for s in shadows" >'+
                                        '</select>'+
                                    '</div>'+
                                    '<div class="zixys-input-box"><input type="button" value="Remove Shadow" ng-click="removeShadow()" id="zixis-sh-removeShadow" ng-disabled="disable"  /></div>'+
                            '</div>'+
                            '<div class="zixys-template-action">'+
                                    '<input type="button" value="Revert" />'+
                            '</div>'+								
                    '</div>',


            link: function($scope, element, attrs) {

            }
        }
    })
    
    .controller('shadowCtrl',['$scope','dataStorage','style',function($scope, dataStorage, style){
        $scope.shadows = [];
        $scope.disable = true;
        $scope.disableAdd = true;
        var counter=0,
            element;

        function Shadow(index) {
            this.top = 0;
            this.left = 0;
            this.blur = 0;
            this.color = {
                rgb : {
                    r:0,
                    g:0,
                    b:0
                },
                alpha:100
            };
            this.size = 0;
            this.inner = false;
            this.index = index;
        }
        
        function generateName() {
            return "sh-"+(counter++);
        }
        
        function valid(param) {
            if( angular.isNumber(param) || angular.isString(param) ){
                return true;
            }
            return false;
        }
        
        function getCssShadow(codeline) {
            return '-moz-box-shadow: '+codeline+';'+ /* Firefox */
                   '-webkit-box-shadow: '+codeline+';'+ /* Safari, Chrome */
                   'box-shadow: '+codeline+';'; /* CSS3 */
        }
        
        function draw() {
            
            if( !$scope.shadow ||
                !valid($scope.shadow.top) ||
                !valid($scope.shadow.left) ||
                !valid($scope.shadow.blur) ||
                !valid($scope.shadow.size)
               ) return;
            
            var codeLine = '';
            
            for(var i=0; i<$scope.shadows.length; i++){
                codeLine = codeLine+
                           $scope.shadows[i].left+'px '+
                           $scope.shadows[i].top+'px '+
                           $scope.shadows[i].blur+'px '+
                           $scope.shadows[i].size+'px '+
                           'rgba( '+
                                $scope.shadows[i].color.rgb.r+', '+
                                $scope.shadows[i].color.rgb.g+', '+
                                $scope.shadows[i].color.rgb.b+', '+
                                parseInt($scope.shadows[i].color.alpha)/100+
                           ') '+ 
                           ($scope.shadows[i].inner? 'inset' : '')+
                           (i!=$scope.shadows.length-1? ', ': '' );
            }
            codeLine = getCssShadow(codeLine);
            style.set(element,'shadow',codeLine);
        }
        
        $scope.addShadow = function(){
            $scope.shadow = new Shadow(generateName());
            $scope.shadows.push($scope.shadow);
            $scope.selected = $scope.shadow;
        }
        
        $scope.removeShadow = function(){
            for (var i=0; i<$scope.shadows.length; i++) {
                if($scope.shadow === $scope.shadows[i]){
                    $scope.shadows.splice(i,1);
                    break;
                }
            }
            if($scope.shadows.length>0){
                $scope.shadow = $scope.selected = $scope.shadows[0];
            }else{
                $scope.shadow = $scope.selected = undefined;
            }
            draw();
        }
        
        $scope.selectShadow = function(){
            $scope.shadow = $scope.selected;
        }
        
        $scope.$on('selectElement',function(event,elem){
            element = elem;
            $scope.disableAdd = false;
            $scope.$apply();
        });
        
        $scope.$watch('shadow',function(newVal){
           draw();
        },true);
        
        $scope.$watch('shadows',function(newVal){
            if(newVal && newVal.length>0){
                $scope.disable = false;
            }else{
                $scope.disable = true;
            }
        },true);

    }])

    .run(['$rootScope','$compile',function($rootScope, $compile){
        
        $rootScope.$on('zixysDomReady',function(event,params){
            $rootScope.addTab('Shadow','shadow-tab',$compile);
        });
        
    }]);
    
    
    'use strict';

var zixysSpinner = function(element,$scope){
        this.isSpinning = false;
        this.timer;
        this.digitsReg = /-*([0-9])+/g;
        this.increment = 0;
        this.currentVal = 0;
        this.currentMeasure = '';
        this.element = element;
        this.delayInc = 300;
        this.$scope = $scope;
        this.min = parseInt(element.attr('min'));
        this.max = parseInt(element.attr('max'));
        
        this.isOutOfRange = function(){return false};
        
        if(!isNaN(this.min) && !isNaN(this.max)){
            this.isOutOfRange = function(x){
                if( (x<this.min) || (x>this.max) ){
                    return true;
                }
                return false;
            }
        }else if(!isNaN(this.min)){
            this.isOutOfRange = function(x){
                if(x<this.min){
                    return true;
                }
                return false;
            }            
        }else if(!isNaN(this.max)){
            this.isOutOfRange = function(x){
                if(x>this.max){
                    return true;
                }
                return false;
            }
        }
}

zixysSpinner.prototype.addUp = function(){
        if(this.isOutOfRange(this.currentVal+this.increment)){
            clearTimeout(this.timer);
            return;
        }
        this.currentVal = this.currentVal+this.increment;
        this.$scope.output = this.element[0].value = this.currentVal+this.currentMeasure;
        this.$scope.$apply();
        this.wait.apply(this);
};

zixysSpinner.prototype.wait = function(){
        var self = this;
        if(this.isSpinning){
            this.timer = setTimeout(function(){
                self.addUp.apply(self);
            },this.delayInc);
            this.delayInc = 10;
        }else{
            clearTimeout(this.timer);
            return;
        }
};

zixysSpinner.prototype.parseValue = function(value){
        this.currentVal = parseInt(value);
        if(isNaN(this.currentVal)){
            this.currentVal = '';
            this.stop();
            return false;
        }
        this.currentMeasure = value.replace(this.digitsReg,'');
        return true;
}

zixysSpinner.prototype.start = function(){
    this.delayInc = 300;
    this.currentVal = '';
    this.currentMeasure = '';
    this.parseValue(this.element[0].value);
    this.addUp();
}

zixysSpinner.prototype.stop = function(){
    clearTimeout(this.timer);
    this.isSpinning = false;
    this.currentVal = '';
    this.currentMeasure = '';
    this.increment = 0; 
}

zixysSpinner.prototype.singleRun = function(){
    
    if(this.parseValue(this.element[0].value)){
        
        if(this.isOutOfRange(this.currentVal)){
           return false; 
        }
        this.$scope.output = this.element[0].value = this.currentVal+this.currentMeasure;
        this.$scope.$apply();
    }
}


angular.module('zixys.styleCollection',[])

    .directive('styleCollection',function(){
        return {
            restrict: 'C',
            replace: false,
            scope: {},
            template:							
                        '<div id="zixys-selector-tab" ng-controller="styleCollectionCtrl" >'+
                            '<div class="zixys-menu-block zixis-small">'+
                                    '<div class="zixys-input-box"><span class="zixys-menu-label">Element:</span><a id="zixys-el-link" class="zixys-menu-label" href="#zixys-pointer">{{pointerName}}</a></div>'+
                            '</div>'+
                            '<div class="zixys-inner-tab long-block" src="css-type-content" style="float:left;width:780px;">'+
                                '<div src="box-model">Box Model</div>'+
                                '<div src="text-style">Text Style</div>'+ 
                            '</div>'+
                            '<div id="css-type-content">'+
                                '<div>'+
                                    '<div class="zixys-menu-block">'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">Width:</span><input class="zixys-spinner" ng-model="width" type="text"></div>'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">Height:</span><input class="zixys-spinner" ng-model="height" type="text"></div>'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">position:</span><input ng-model="position" type="text"></div>'+
                                    '</div>'+
                                    '<div class="zixys-menu-block">'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">margin:</span>'+
                                                    '<input class="zxyMinInpt zixys-spinner" ng-model="marginTop" type="text">'+
                                                    '<input class="zxyMinInpt zixys-spinner" ng-model="marginRight" type="text">'+
                                                    '<input class="zxyMinInpt zixys-spinner" ng-model="marginBottom" type="text">'+
                                                    '<input class="zxyMinInpt zixys-spinner" ng-model="marginLeft" type="text"></div>'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">padding:</span>'+
                                                    '<input class="zxyMinInpt zixys-spinner" ng-model="paddingTop" type="text">'+
                                                    '<input class="zxyMinInpt zixys-spinner" ng-model="paddingRight" type="text">'+
                                                    '<input class="zxyMinInpt zixys-spinner" ng-model="paddingBottom" type="text">'+
                                                    '<input class="zxyMinInpt zixys-spinner" ng-model="paddingLeft" type="text">'+
                                            '</div>'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">Display:</span><input ng-model="display" type="text"></div>'+

                                    '</div>'+
                                    '<div class="zixys-menu-block">'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">bord.-top:</span><input type="text"></div>'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">bord.-right:</span><input type="text"></div>'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">bord.-bottom:</span><input type="text"></div>'+
                                    '</div>'+
                                    '<div class="zixys-menu-block">'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">bord.-left:</span><input type="text"></div>'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">pos. X:</span><input readonly="readonly" class="zixys-disabled-input" type="text"></div>'+
                                            '<div class="zixys-input-box"><span class="zixys-menu-label">pos. Y:</span><input readonly="readonly" class="zixys-disabled-input" type="text"></div>'+
                                    '</div>'+

                                '</div>'+
                                '<div>'+
                                    'teeeest'+
                                '</div>'+
                            '</div>'+
                            '<div id="zixys-pointer"></div>'+
                        '</div>',

            link: function($scope, element, attrs) {
                var pointer = element.find('#zixys-pointer').appendTo('body').hide();
                var pointerLink = element.find('#zixys-el-link');
                var selectedElement;
                
                pointerLink.mouseover(function(){
                    if(!selectedElement){
                        return;
                    }
                    pointer.width(selectedElement.outerWidth());
                    pointer.height(selectedElement.outerHeight());
                    pointer.css({
                        top:selectedElement.offset().top,
                        left:selectedElement.offset().left
                    });
                    pointer.show();
                }).mouseout(function(){
                    pointer.hide();
                });
                
                $scope.$root.$on('selectElement',function(event,selElem){
                    selectedElement = selElem;
                })
            }
        }
    })
    
    .controller('styleCollectionCtrl',['$scope','dataStorage','style',function($scope,dataStorage, style){
        var element;
        var selectInProgress;
        var collection = [
            'width',
            'height',
            'position',
            'marginTop',
            'marginRight',
            'marginBottom',
            'marginLeft',
            'paddingTop',
            'paddingRight',
            'paddingBottom',
            'paddingLeft',
            'display'
        ]
        
        var toHyphens = function(propName){
            return propName.replace(/([a-z][A-Z])/g, function (g) { return g[0] + '-' + g[1].toLowerCase() })
        }
        
        var applyStyle = function(styleProp,value){
            styleProp = toHyphens(styleProp);
            style.set(element, styleProp, styleProp+':'+value+';');
            dataStorage.save('Element',styleProp,value);
        }
        
        var registerWatcher = function(propName){
            $scope.$watch(propName,function(newVal){
                if(selectInProgress === false){
                    applyStyle(propName,newVal);
                }
            });   
        }
        for(var i=0; i<collection.length;i++){
            registerWatcher(collection[i]);
        }
        
        var getElementSelector = function(element){
            var classNames = '';
            var elementSelector = '';
			
            if(element[0].tagName){
                elementSelector = elementSelector + element[0].tagName;
            }
            if(element.attr('id')){
                elementSelector = elementSelector + '#' + element.attr('id');
            }
            if(element.attr('class')){
                classNames = element.attr('class');
                classNames = classNames.replace(/(\s+(zixys-hovered-item)|(zixys-hovered-item))/g,'');
                classNames = classNames.replace(/\s+/g,'.');
                if(classNames){
                    elementSelector = elementSelector +'.'+classNames;
                }
            }
            return elementSelector;
        }

        $scope.$root.$on('selectElement',function(event,_element){
            element = _element;
            $scope.pointerName = getElementSelector(element);
            for(var i=0; i<collection.length; i++){
                try{ $scope[collection[i]] = element.css(collection[i]) }
                catch(err){
                    console.log(err);
                };
            }
            selectInProgress = true;
            $scope.$apply();
            selectInProgress = false;
        });
        
    }])

    .run(['$rootScope','$compile',function($rootScope,$compile){
        
        $rootScope.$on('zixysDomReady',function(event,params){
            $rootScope.addTab('Element','style-collection',$compile);
        });
        
    }]);
    


angular.module('zixys', [
    'zixys.services', 
    'zixys.directives',
    'zixys.domSelector',
    'zixys.styleCollection',
    'zixys.gradient',
    'zixys.shadow'])
    
    .run(['$rootScope',function($rootScope){
        
        $rootScope.test = true;
        
    }]);


window.zixysReady = true;